
namespace Kaleta.Xna.Collision
{
    // .NET Fx
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.InteropServices;

    // XNA
    using Microsoft.Xna.Framework;

    public partial class Sap
    {
        /// <summary>Used for the GetEnumerator method</summary>
        /// <remarks>When possible and practical, specifically enumerating through this type
        /// (instead of IEnumerable) can prevent some GC costs associated with boxing</remarks>
        [StructLayout(LayoutKind.Auto)]
        public struct Enumerator : IEnumerable<IBody>, IEnumerator<IBody>
        {
            #region Fields
            // Private variables
            private readonly Sap instance;
            //private readonly int version;
            private int index;
            private IBody current;
            #endregion

            internal Enumerator(Sap instance)
            {
                #region Assertions
                Debug.Assert(instance != null);
                Debug.Assert(instance.bodies != null);
                //Debug.Assert(instance.markers != null);
                Debug.Assert(instance.count <= instance.bodies.Length);
                //Debug.Assert(instance.bodies.Length == instance.markers.Length);
	            #endregion

                this.instance = instance;
                //this.version = instance.version;
                this.index = 0;
                this.current = null;
            }

            #region Methods
            public IBody Current
            {
                get { return this.current; }
            }

            public Enumerator GetEnumerator()
            {
                return this;
            }

            public bool MoveNext()
            {

                if (this.index < this.instance.count)
				{
					// TODO: Instrument
                    // Current becomes the body of the current entry and index is incremented
                    // for next time..
                    this.current = this.instance.bodies[this.index++];
                    return true;
                }
                else
                    return false;
            } 
            #endregion

            #region IEnumerable<Body> Members
            IEnumerator<IBody> IEnumerable<IBody>.GetEnumerator()
            {
                return this;
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return this;
            }
            #endregion

            #region IEnumerator<Body> Members
            IBody IEnumerator<IBody>.Current
            {
                get { return this.Current; }
            }

            void IDisposable.Dispose()
            {
            }

            object IEnumerator.Current
            {
                get { return this.Current; }
            }

            bool IEnumerator.MoveNext()
            {
                return this.MoveNext();
            }

            void IEnumerator.Reset()
            {
                this.index = 0;
                this.current = null;
            }
            #endregion
        }
    }
}
